JavaScript数据结构与算法

218次阅读
没有评论

共计 7737 个字符,预计需要花费 20 分钟才能阅读完成。

数组结构

参考:http://8.129.6.198/post/173/

栈结构

栈 (stack) 又名堆栈,是一种运算受限的线性表,限定仅在表尾进行插入和删除操作。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素称作进栈,从一个栈删除元素称作出栈。

特点:后进先出,即 Last in First out (LIFO)。

class Stack {#items = [] //# 符号声明私有属性,ES13 新特性

  pop() {return this.#items.pop() // 出栈
  }

  push(data) {return this.#items.push(data) // 进栈
  }

  peek() {return this.#items.at(-1) // 栈顶
  }

  isEmpty() {return this.#items.length === 0}

  size() {return this.#items.length}

  clear() {this.#items = []
  }

  toString() {return this.#items.join(" ")
  }
}

// 十进制转 2 8 16 进制
function convert(decNumber, base) {let remStack = new Stack()
  let number = decNumber
  let string = ""
  let baseString = "0123456789ABCDEF"

  while (number > 0) {remStack.push(number % base)
    number = Math.floor(number / base)
  }

  while (!remStack.isEmpty()) {string += baseString[remStack.pop()]
  }

  return string
}

convert(500, 16)

队列结构

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端进行删除操作,而在表的后端进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾(入队),进行删除操作的端称为队头(出队)。队列中没有元素时,称为空队列。

特点:先进先出,即 First in First out(FIFO)。

封装与应用

class Queue {#items = {}
  #lowCount = 0
  #count = 0

  dequeue() {if (this.isEmpty()) {return undefined}

    let res = this.#items[this.#lowCount]
    delete this.#items[this.#lowCount]
    this.#lowCount++
    return res // 出队
  }

  enqueue(data) {this.#items[this.#count] = data // 入队
    this.#count++
  }

  front() {return this.#items[this.#lowCount] // 队头
  }

  isEmpty() {return this.size() === 0
  }

  size() {return this.#count - this.#lowCount}

  clear() {this.#items = {}
    this.#count = 0
    this.#lowCount = 0
  }

  toString() {
    let str = ""
    for (let i = this.#lowCount; i < this.#count; i++) {str += `${this.#items[i]} `
    }

    return str
  }
}

// 击鼓传花游戏
function game(list, num) {let queue = new Queue()
  for (let i = 0; i < list.length; i++) {queue.enqueue(list[i])
  }

  while (queue.size() > 1) {for (let i = 0; i < num; i++) {queue.enqueue(queue.dequeue())
    }

    console.log(queue.dequeue(), " 淘汰了 ")
  }

  return queue.dequeue() + " 获胜 "}

game([" 张三 ", " 李四 ", " 王五 ", " 赵六 ", " 孙七 "], 7)

双端队列

class DeQueue {#items = {}
  #lowCount = 0 // 队头索引
  #count = 0

  removeFront() {if (this.isEmpty()) {return undefined}

    let res = this.#items[this.#lowCount]
    delete this.#items[this.#lowCount]
    this.#lowCount++

    return res
  }

  removeBack() {if (this.isEmpty()) {return}

    this.#count--
    const res = this.#items[this.#count]
    delete this.#items[this.#count]

    return res
  }

  addFront(data) {if (this.isEmpty()) {this.addBack(data)
    } else {if (this.#lowCount > 0) {
        this.#lowCount--
        this.#items[this.#lowCount] = data
      } else {
        // #lowCount=0
        for (let i = this.#count; i > 0; i--) {this.#items[i] = this.#items[i - 1]
        }
      }
    }
  }

  addBack(data) {this.#items[this.#count] = data
    this.#count++
  }

  peekFront() {return this.#items[this.#lowCount]
  }

  peekBack() {return this.#items[this.#count - 1]
  }

  isEmpty() {return this.size() === 0
  }

  size() {return this.#count - this.#lowCount}

  clear() {this.#items = {}
    this.#count = 0
    this.#lowCount = 0
  }

  toString() {
    let str = ""
    for (let i = this.#lowCount; i < this.#count; i++) {str += `${this.#items[i]} `
    }

    return str
  }
}

// 回文字符串检查
function test(str) {const lowstr = str.toLocaleLowerCase().split(" ").join("")
  let dequeue = new DeQueue()

  for (let i = 0; i < lowstr.length; i++) {dequeue.addBack(lowstr[i])
  }

  let isEqual = true
  while (dequeue.size() > 1) {if (dequeue.removeFront() != dequeue.removeBack()) {
      isEqual = false
      break
    }
  }

  return isEqual
}

test(" 上海自来水来自海上 ")

链表

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点 (链表中每一个元素称为结点) 组成,结点可以在运行时动态生成。每个结点包括两个部分: 一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

链表的特点

  1. 插入、删除数据效率高 O(1)级别 (只需更改指针指向即可),随机访问效率低 O(n) 级别(需要从链头至链尾进行遍历)
  2. 和数组相比,内存空间消耗更大,因为每个存储数据的节点都需要额外的空间存储后继指针。

单链表

每个节点只包含一个指针,即后继指针。

class Node {constructor(element) {
    this.element = element
    this.next = null
  }
}

class LinkedList {constructor() {
    this.count = 0
    this.head = null
  }

  push(element) {const node = new Node(element)

    if (this.head === null) {this.head = node} else {
      let current = this.head

      while (current.next !== null) {current = current.next}

      current.next = node
    }

    this.count++
  }

  getNodeAt(index) {if (index >= 0 && index < this.count) {
      let node = this.head
      for (let i = 0; i < index; i++) {node = node.next}

      return node
    }

    return
  }

  // 指定位置删除
  removeAt(index) {if (index >= 0 && index < this.count) {
      let current = this.head
      if (index === 0) {this.head = this.head.next} else {let previous = this.getNodeAt(index - 1)
        current = previous.next
        previous.next = current.next
      }

      this.count--
      return current.element
    }

    return
  }

  equalFn(a, b) {return JSON.stringify(a) === JSON.stringify(b)
  }

  indexOf(element) {
    let current = this.head
    for (let i = 0; i < index; i++) {if (this.equalFn(element, current.element)) {return i}
      current = current.next
    }

    return -1
  }

  // 指定元素删除
  remove(element) {const index = this.indexOf(element)
    return this.removeAt(index)
  }

  insert(element, index) {if (index >= 0 && index <= this.count) {const node = new Node(element)
      if (index === 0) {
        const current = this.head
        node.next = current
        this.head = node
      } else {const previous = this.getNodeAt(index - 1)
        const current = previous.next

        node.next = current
        previous.next = node
      }

      this.count++
      return true
    }

    return false
  }

  isEmpty() {return this.size() === 0
  }

  size() {return this.count}

  getHead() {return this.head}
}

// 回文字符串检查
function test(str) {const lowstr = str.toLocaleLowerCase().split(" ").join("")
  let sll = new LinkedList()

  for (let i = 0; i < lowstr.length; i++) {sll.push(lowstr[i])
  }

  let isEqual = true
  while (sll.size() > 1) {if (sll.removeAt(0) !== sll.removeAt(sll.size() - 1)) {
      isEqual = false
      break
    }
  }

  return isEqual
}

test(" 上海自来水来自海上 ")

击鼓传花游戏使用单链表:

// 击鼓传花游戏
function game(list, num) {let queue = new LinkedList()
  for (let i = 0; i < list.length; i++) {queue.push(list[i])
  }

  while (queue.size() > 1) {for (let i = 0; i < num; i++) {queue.push(queue.removeAt(0))
    }

    console.log(queue.removeAt(0), " 淘汰了 ")
  }

  return queue.removeAt(0) + " 获胜 "
}

game([" 张三 ", " 李四 ", " 王五 ", " 赵六 ", " 孙七 "], 7)

十进制转 2 8 16 进制:

// 十进制转 2 8 16 进制
function convert(decNumber, base) {let remStack = new LinkedList()
  let number = decNumber
  let string = ""
  let baseString = "0123456789ABCDEF"

  while (number > 0) {remStack.push(number % base)
    number = Math.floor(number / base)
  }

  while (!remStack.isEmpty()) {string += baseString[remStack.removeAt(remStack.size() - 1)]
  }

  return string
}

convert(500, 16)

双链表

class DoublyNode extends Node {constructor(element) {super(element)
    this.prev = null
  }
}

class DoublyLinkedList extends LinkedList {constructor() {super()
    this.tail = null
  }

  push(element) {const node = new DoublyNode(element)
    if (this.head === null) {
      this.head = node
      this.tail = node
    } else {
      this.tail.next = node
      node.prev = this.tail
      this.tail = node
    }

    this.count++
  }

  remove(element) {const index = this.indexOf(element)
    return this.removeAt(index)
  }

  insert(element, index) {if (index >= 0 && index <= this.count) {const node = new DoublyNode(element)
      let current = this.head
      if (index === 0) {if (this.head === null) {
          this.head = node
          this.tail = node
        } else {
          node.next = this.head
          this.head.prev = node
          this.head = node
        }
      } else if (index === this.count) {
        current = this.tail
        current.next = node
        node.prev = current
        this.tail = node
      } else {const previous = this.getNodeAt(index - 1)
        current = previous.next

        node.next = current
        current.prev = node
        previous.next = node
        node.prev = previous
      }

      this.count++
      return true
    }

    return false
  }

  removeAt(index) {if (index >= 0 && index < this.count) {
      let current = this.head
      if (index === 0) {
        this.head = current.next
        if (this.count === 1) {this.tail = null} else {this.head.prev = null}
      } else if (index === this.count - 1) {
        current = this.tail
        this.tail = current.prev
        this.tail.next = null
      } else {let previous = this.getNodeAt(index - 1)
        current = previous.next
        previous.next = current.next
        current.next.prev = previous
      }

      this.count--
      return current.element
    }

    return
  }

  getHead() {return this.head}

  getTail() {return this.tail}
}

循环链表

循环链表和链表之间唯一的区别在于,最后一个元素指向下一个元素的指针 (tail.next) 不是 undefined,而是指向第一个元素(head)。

class CircularLinkedList extends LinkedList {constructor() {super()
  }

  push(element) {const node = new Node(element)
    let current
    if (this.head === null) {this.head = node} else {current = this.getNodeAt(this.size() - 1)
      current.next = node
    }

    node.next = this.head
    this.count++
  }

  insert() {if (index >= 0 && index <= this.count) {const node = new Node(element)
      let current = this.head
      if (index === 0) {if (this.head === null) {
          this.head = node
          node.next = this.head
        } else {
          node.next = current
          this.head = node

          current = this.getNodeAt(this.size() - 1)
          current.next = this.head
        }
      } else {const previous = this.getNodeAt(index - 1)
        node.next = previous.next
        previous.next = node
      }

      this.count++
      return true
    }

    return false
  }

  removeAt(index) {if (index >= 0 && index < this.count) {
      let current = this.head
      if (index === 0) {if (this.size() === 1) {this.head = null} else {let last = this.getNodeAt(this.size() - 1)
          this.head = this.head.next
          last.next = this.head
        }
      } else {const previous = this.getNodeAt(index - 1)
        current = previous.next
        previous.next = current.next
      }

      this.count--
      return current.element
    }

    return
  }
}

正文完
 0
阿伯手记
版权声明:本站原创文章,由 阿伯手记 于2023-08-29发表,共计7737字。
转载说明:本站原创内容,除特殊说明外,均基于 CC BY-NC-SA 4.0 协议发布,转载须注明出处与链接。
评论(没有评论)
验证码

阿伯手记

阿伯手记
阿伯手记
喜欢编程,头发渐稀;成长路上,宝藏满地
文章数
766
评论数
204
阅读量
449909
今日一言
-「
热门文章
职场救急!AI请假话术生成器:1秒定制高通过率理由

职场救急!AI请假话术生成器:1秒定制高通过率理由

超级借口 不好开口?借口交给我!智能生成工作请假、上学请假、饭局爽约、约会拒绝、邀约推辞、万能借口等各种借口理...
夸克网盘快传助手提高非VIP下载速度

夸克网盘快传助手提高非VIP下载速度

夸克网盘限速这个大家都知道,不开会员差不多限速在几百 K。那有没有办法在合法合规途径加速下载夸克网盘呢?这里推...
国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

本文收集了目前国内已部署 DeepSeek 模型的第三方列表,个个都是免费不限次数的满血版 DeepSeek,...
巴别英语:用美剧和TED演讲轻松提升英语听力与口语

巴别英语:用美剧和TED演讲轻松提升英语听力与口语

还在为枯燥的英语学习而烦恼吗?巴别英语通过创新的美剧学习模式,让英语学习变得生动有趣。平台提供海量美剧和 TE...
Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 是一款在线中文姓名生成器,可在几秒内生成符合个人需求的中文名字。...
TVAPP:开源电视盒子资源库,一键打造家庭影院

TVAPP:开源电视盒子资源库,一键打造家庭影院

导语 TVAPP 是一个专为 Android TV 电视盒子用户打造的开源影音资源库,集成了影视、直播、游戏等...
2025年12月 每日精选

2025年12月 每日精选

关于每日精选栏目 发现一些不错的资源,点击 这里 快速投稿。 12 月 26 日 .ax 顶级域 目前全球唯一...
最新评论
15220202929 15220202929 怎么用
八对 八对 麻烦大佬更新下【堆新】的友链站名:八对星星描述:极目星视穹苍无界•足履行者大地有疆链接:https://8dui.com图标:https://cf.8dui.com/logo.webp横标:https://cf.8dui.com/logo-w.webp订阅:https://8dui.com/rss.xml
三毛笔记 三毛笔记 已添加
DUINEW DUINEW 已添加贵站,期待贵站友链~博客名称:堆新博客地址:https://duinew.com/博客描述:堆新堆新,引力向新!——堆新(DUINEW)博客头像:https://d.duinew.com/logo.webp横版头像:https://d.duinew.com/logo-w.webp博客订阅:https://duinew.com/rss.xml
hedp hedp 没看懂
bingo bingo 直接生成就可以啦,也可以添加一些选项
满心 满心 申请更新下友联信息,原名:满心记,现名:周天记原域名:qq.mba,现域名:zhoutian.com描述:我在人间混日子
开业吉日 开业吉日 没看明白这个怎么用
开业吉日 开业吉日 beddystories 这个网站太赞了,收藏
热评文章
夸克网盘快传助手提高非VIP下载速度

夸克网盘快传助手提高非VIP下载速度

夸克网盘限速这个大家都知道,不开会员差不多限速在几百 K。那有没有办法在合法合规途径加速下载夸克网盘呢?这里推...
清华大学官方免费DeepSeek教程

清华大学官方免费DeepSeek教程

AI 领域近期最引人注目的焦点当属 DeepSeek,这款由中国创新企业深度求索研发的人工智能工具,正以开放源...
Short-Link 免费开源短网址程序,基于Fastify、Vercel和Supabase构建

Short-Link 免费开源短网址程序,基于Fastify、Vercel和Supabase构建

Short-Link 是一款基于 Fastify、Vercel 和 Supabase 构建的 URL 缩短服务...
国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

本文收集了目前国内已部署 DeepSeek 模型的第三方列表,个个都是免费不限次数的满血版 DeepSeek,...
Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 是一款在线中文姓名生成器,可在几秒内生成符合个人需求的中文名字。...
BeddyStories 完全免费儿童睡前故事库,让孩子随时随地入睡更轻松

BeddyStories 完全免费儿童睡前故事库,让孩子随时随地入睡更轻松

BeddyStories 是一个致力于为儿童提供优质睡前故事的在线平台,用户可以在这里找到来自世界各地的经典故...
DrawLink:一键生成链接视觉卡片,提升分享点击率

DrawLink:一键生成链接视觉卡片,提升分享点击率

小贴士 :此站或已变迁,但探索不止步。我们已为您备好「类似网站」精选合集,相信其中的发现同样能为您带来惊喜。